package client;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import miscellaneous.Storage;
import mockup.AppointmentMockup;
import mockup.InviteMockup;
import mockup.MeetingMockup;
import mockup.Mockup;
import mockup.MockupToData;
import mockup.UserMockup;
import client.tcp.ClientTCP;
import data.Appointment;
import data.Data;
import data.Invite;
import data.Meeting;
import data.Message;
import data.User;
import data.room.Room;

/**
 * Receives objects from the clients ClientTCP socket
 * @author Erik
 * @author daniel
 *
 */
public class Receiver implements Runnable {

	private static boolean run = true;

	/**
	 * Creates a new thread to receive object from the socket
	 */
	public static void startReceiving() {
		Thread thread = new Thread(new Receiver());
		thread.start();
	}

	@Override
	public void run() {
		while(run) {
			ClientTCP socket = Storage.getSocket();

			if(socket != null && socket.isConnected()) {				
				Mockup packet = new Mockup(-1);
				packet.setSessionId(Storage.getSessionID());
				packet.setState(Mockup.GET_CREATED);
				
				Serializable answer = socket.send(packet);
				if(answer instanceof ArrayList<?>) {
					@SuppressWarnings("unchecked")
					List<Mockup> list = (ArrayList<Mockup>) answer;
					for(Mockup mockup: list) {
						Data data = MockupToData.getData(mockup);
						if(data instanceof Meeting) {
							Storage.meetings.insert((Meeting)data);
							Storage.reservations.put(((Meeting)data).getReservation().getId(),((Meeting)data).getReservation());
						}
						else if(data instanceof Appointment) {
							Storage.appointments.insert((Appointment)data);
							Storage.reservations.put(((Appointment)data).getReservation().getId(),((Appointment)data).getReservation());
						} else if(data instanceof Room) {
							Storage.rooms.put(data.getId(),(Room)data);
						} else if(data instanceof Message) {
							Storage.messages.insert((Message)data);
						} else if(data instanceof User) {
							Storage.users.insert((User)data);
						}
					}
				}
				
				packet.setState(Mockup.GET_REMOVED);
				
				answer = socket.send(packet);
				if(answer instanceof ArrayList<?>) {
					@SuppressWarnings("unchecked")
					List<Mockup> list = (ArrayList<Mockup>) answer;
					for(Mockup mockup: list) {
						Data data = MockupToData.getData(mockup);
						if(data instanceof Meeting) {
							Storage.meetings.deleteByID(data.getId());
							Storage.reservations.remove(((Meeting)data).getReservation().getId());
						} else
						if(data instanceof Appointment) {
							Storage.appointments.deleteByID(data.getId());
							Storage.reservations.remove(((Appointment)data).getReservation().getId());
						} else if(data instanceof Invite) {
							Storage.messages.deleteByID(data.getId());
						}
					}
				}
				
				packet.setState(Mockup.GET_CHANGED);
				answer = socket.send(packet);
				if(answer instanceof ArrayList<?>) {
					@SuppressWarnings("unchecked")
					List<Mockup> list = (ArrayList<Mockup>) answer;
					for(Mockup mockup: list) {
						Data data = MockupToData.getData(mockup);
							if(data instanceof Meeting) {
								Storage.meetings.deleteByID(data.getId());
								Storage.reservations.remove(((Meeting)data).getReservation().getId());
								Meeting meeting = MockupToData.getMeeting((MeetingMockup)mockup);
								Storage.meetings.insert(meeting);
								Storage.reservations.put(meeting.getReservation().getId(), meeting.getReservation());
							} else if(data instanceof Appointment) {
								Storage.appointments.deleteByID(data.getId());
								Storage.reservations.remove(((Appointment)data).getReservation().getId());
								Appointment appointment = MockupToData.getAppointment((AppointmentMockup)mockup);
								Storage.appointments.insert(appointment);
								Storage.reservations.put(appointment.getReservation().getId(), appointment.getReservation());
							} else if(data instanceof Invite) {
								Storage.messages.deleteByID(data.getId());
								Storage.messages.insert(MockupToData.getInvite((InviteMockup)mockup));;
							} else if(data instanceof User) {
								Storage.users.deleteByID(data.getId());
								Storage.users.insert(MockupToData.getUser((UserMockup)mockup));
							}
					}
				}
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
				}
			}
		}
	}

	/**
	 * Causes all threads to stop executing within 10 milliseconds
	 */
	public void disableThreads() {
		run = false;
	}

	/**
	 * Enables threads to run after a stop
	 */
	public void enableThreads() {
		run = true;
	}

}
